package com.example.demo.application.myredis;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.example.demo.application.myredis.serialize.ObjectsTranscoder;
import com.google.common.collect.Maps;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisCluster;

/**
 * 该类 由于 使用new ObjectsTranscoder() ，而不是单例模式，有内存溢出风险 <一句话功能简述> redis 缓存对象处理
 * <功能详细描述>
 * 
 * @author Administrator
 * @version [版本号，2017年5月11日]
 * @see [相关类/方法]
 * @since [产品/模块版本]
 */
public class RedisHelper extends RedisProvider {
	
	static {
		if (ReloadConfig.isnoInit) {
			ReloadConfig.init();
		}
	}

	protected static final Logger logger = LoggerFactory.getLogger(RedisHelper.class);

	/**
	 * Set the string value as value of the key. Default settings at save
	 * time(2000s)
	 * 
	 * @param key
	 * @param value
	 * @return
	 */
	public static String set(String key, String value) {
		String rtn = null;
		if (ReloadConfig.isUseCluster) {
			JedisCluster jedis = null;
			try {
				jedis = getJedisCluster();
				rtn = jedis.setex(key, EXPIRE, value);
			} catch (Exception e) {
				logger.error(e.getMessage(), e);
				reload();
			}
		} else {
			Jedis jedis = null;
			try {
				jedis = getJedis();
				rtn = jedis.setex(key, EXPIRE, value);
			} catch (Exception e) {
				logger.error(e.getMessage(), e);
				reload();
			} finally {
				jedis.close();
			}
		}
		return rtn;
	}
	
	public static String set(String key, String value, int timeOut) {
		String rtn = null;
		if (ReloadConfig.isUseCluster) {
			JedisCluster jedis = null;
			try {
				jedis = getJedisCluster();
				rtn = jedis.setex(key, timeOut, value);
			} catch (Exception e) {
				logger.error(e.getMessage(), e);
				reload();
			}
		} else {
			Jedis jedis = null;
			try {
				jedis = getJedis();
				rtn = jedis.setex(key, timeOut, value);
			} catch (Exception e) {
				logger.error(e.getMessage(), e);
				reload();
			} finally {
				jedis.close();
			}
		}
		return rtn;
	}

	/**
	 * Get the value of the specified key.
	 * 
	 * @param key
	 * @return
	 */
	public static String get(String key) {
		String rtn = null;
		if (ReloadConfig.isUseCluster) {
			JedisCluster jedis = null;
			try {
				jedis = getJedisCluster();
				rtn = jedis.get(key);
			} catch (Exception e) {
				logger.error(e.getMessage(), e);
			}
		} else {
			Jedis jedis = null;
			try {
				jedis = getJedis();
				rtn = jedis.get(key);
			} catch (Exception e) {
				logger.error(e.getMessage(), e);
			} finally {
				jedis.close();
			}
		}
		return rtn;
	}

	/**
	 * Set the the respective keys to the respective values.
	 * 
	 * @param keysvalues
	 * @return
	 */
	public static String mset(String... keysvalues) {
		String rtn = null;
		if (ReloadConfig.isUseCluster) {
			// TODO JedisCluster 不能 一次性设置多个KV,
			JedisCluster jedis = null;
			try {
				jedis = getJedisCluster();
				rtn = jedis.mset(keysvalues);
			} catch (Exception e) {
				logger.error(e.getMessage(), e);
			}
		} else {
			Jedis jedis = null;
			try {
				jedis = getJedis();
				rtn = jedis.mset(keysvalues);
			} catch (Exception e) {
				logger.error(e.getMessage(), e);
			}finally {
				jedis.close();
			}
		}
		return rtn;
	}

	/**
	 * Get the values of all the specified keys
	 * 
	 * @param keys
	 * @return
	 */
	public static List<String> mget(String... keys) {
		List<String> rtn = new ArrayList<String>();
		if (ReloadConfig.isUseCluster) {
			JedisCluster jedis = null;
			try {
				jedis = getJedisCluster();
				rtn = jedis.mget(keys);
			} catch (Exception e) {
				logger.error(e.getMessage(), e);
			}
		} else {
			Jedis jedis = null;
			try {
				jedis = getJedis();
				rtn = jedis.mget(keys);
			} catch (Exception e) {
				logger.error(e.getMessage(), e);
			}finally {
				jedis.close();
			}
		}
		return rtn;
	}

	public static long mdel(String[] key) {
		Long rtn = null;
		if (ReloadConfig.isUseCluster) {
			JedisCluster jedis = null;
			try {
				jedis = getJedisCluster();
				rtn = jedis.del(key);
			} catch (Exception e) {
				logger.error(e.getMessage(), e);
			}
		} else {
			Jedis jedis = null;
			try {
				jedis = getJedis();
				rtn = jedis.del(key);
			} catch (Exception e) {
				logger.error(e.getMessage(), e);
			}finally {
				jedis.close();
			}
		}
		return rtn;
	}

	/**
	 * Return all the fields and associated values in a hash.
	 * 
	 * @param key
	 * @return
	 */
	public static Map<String, String> hgetall(String key) {
		Map<String, String> rtn = Maps.newHashMap();
		if (ReloadConfig.isUseCluster) {
			JedisCluster jedis = null;
			try {
				jedis = getJedisCluster();
				rtn = jedis.hgetAll(key);
			} catch (Exception e) {
				logger.error(e.getMessage(), e);
			}
		} else {
			Jedis jedis = null;
			try {
				jedis = getJedis();
				rtn = jedis.hgetAll(key);
			} catch (Exception e) {
				logger.error(e.getMessage(), e);
			}finally {
				jedis.close();
			}
		}
		return rtn;
	}

	/**
	 * Set the specified hash field to the specified value.
	 * 
	 * @param key
	 * @param field
	 * @param value
	 * @return
	 */
	public static Long hset(String key, String field, String value) {
		Long rtn = null;
		if (ReloadConfig.isUseCluster) {
			JedisCluster jedis = null;
			try {
				jedis = getJedisCluster();
				rtn = jedis.hset(key, field, value);
				jedis.expire(key, EXPIRE);
			} catch (Exception e) {
				logger.error(e.getMessage(), e);
			}
		} else {
			Jedis jedis = null;
			try {
				jedis = getJedis();
				rtn = jedis.hset(key, field, value);
				jedis.expire(key, EXPIRE);
			} catch (Exception e) {
				logger.error(e.getMessage(), e);
			}finally {
				jedis.close();
			}
		}
		return rtn;
	}

	public static String hget(String key, String field) {
		String rtn = null;
		if (ReloadConfig.isUseCluster) {
			JedisCluster jedis = null;
			try {
				jedis = getJedisCluster();
				rtn = jedis.hget(key, field);
			} catch (Exception e) {
				logger.error(e.getMessage(), e);
			}
		} else {
			Jedis jedis = null;
			try {
				jedis = getJedis();
				rtn = jedis.hget(key, field);
			} catch (Exception e) {
				logger.error(e.getMessage(), e);
			}finally {
				jedis.close();
			}
		}
		return rtn;
	}

	public static long hdel(String key, String[] field) {
		Long rtn = null;
		if (ReloadConfig.isUseCluster) {
			JedisCluster jedis = null;
			try {
				jedis = getJedisCluster();
				rtn = jedis.hdel(key, field);
			} catch (Exception e) {
				logger.error(e.getMessage(), e);
			}
		} else {
			Jedis jedis = null;
			try {
				jedis = getJedis();
				rtn = jedis.hdel(key, field);
			} catch (Exception e) {
				logger.error(e.getMessage(), e);
			}finally {
				jedis.close();
			}
		}
		return rtn;
	}

	/**
	 * 以map形式存放对象.
	 * 
	 * @param key
	 * @param field
	 * @param obj
	 * @return
	 */
	public static long setObject(String key, String field, Object obj) {
		Long rtn = null;
		if (ReloadConfig.isUseCluster) {
			JedisCluster jedis = null;
			try {
				jedis = getJedisCluster();
				rtn = jedis.hset(key.getBytes(), field.getBytes(), new ObjectsTranscoder().serialize(obj));
			} catch (Exception e) {
				logger.error(e.getMessage(), e);
			}
		} else {
			Jedis jedis = null;
			try {
				jedis = getJedis();
				rtn = jedis.hset(key.getBytes(), field.getBytes(), new ObjectsTranscoder().serialize(obj));
			} catch (Exception e) {
				logger.error(e.getMessage(), e);
			}finally {
				jedis.close();
			}
		}
		return rtn;
	}

	/**
	 * 获取对象.
	 * 
	 * @param key
	 * @param field
	 * @return
	 */
	public static Object getObject(String key, String field) {
		byte[] rtn = null;
		if (ReloadConfig.isUseCluster) {
			JedisCluster jedis = null;
			try {
				jedis = getJedisCluster();
				rtn = jedis.hget(key.getBytes(), field.getBytes());
			} catch (Exception e) {
				logger.error(e.getMessage(), e);
			}
		} else {
			Jedis jedis = null;
			try {
				jedis = getJedis();
				rtn = jedis.hget(key.getBytes(), field.getBytes());
			} catch (Exception e) {
				logger.error(e.getMessage(), e);
			}finally {
				jedis.close();
			}
		}
		return new ObjectsTranscoder().deserialize(rtn);
	}

	public static void addObject(String key, Object obj) {
		if (ReloadConfig.isUseCluster) {
			JedisCluster jedis = null;
			try {
				jedis = getJedisCluster();
				jedis.sadd(key.getBytes(), new ObjectsTranscoder().serialize(obj));
				jedis.expire(key.getBytes(), EXPIRE);
			} catch (Exception e) {
				logger.error(e.getMessage(), e);
			}
		} else {
			Jedis jedis = null;
			try {
				jedis = getJedis();
				jedis.sadd(key.getBytes(), new ObjectsTranscoder().serialize(obj));
				jedis.expire(key.getBytes(), EXPIRE);
			} catch (Exception e) {
				logger.error(e.getMessage(), e);
			}finally {
				jedis.close();
			}
		}
	}
	
	/**
	 * <功能> 
	 * <详细描述> 
	 * @param key
	 * @param obj
	 * @param expiretime 秒
	 * @see [类、类#方法、类#成员]
	 */
	public static void addObject(String key, Object obj, int expiretime) {
		if (ReloadConfig.isUseCluster) {
			JedisCluster jedis = null;
			try {
				jedis = getJedisCluster();
				jedis.sadd(key.getBytes(), new ObjectsTranscoder().serialize(obj));
				jedis.expire(key.getBytes(), expiretime);
			} catch (Exception e) {
				logger.error(e.getMessage(), e);
			}
		} else {
			Jedis jedis = null;
			try {
				jedis = getJedis();
				jedis.sadd(key.getBytes(), new ObjectsTranscoder().serialize(obj));
				jedis.expire(key.getBytes(), expiretime);
			} catch (Exception e) {
				logger.error(e.getMessage(), e);
			}finally {
				jedis.close();
			}
		}
	}

	/**
	 * <一句话功能简述> <功能详细描述>
	 * 
	 * @param key
	 * @return
	 * @see [类、类#方法、类#成员]
	 */
	public static List<? extends Object> getAllObject(String key) {
		List<Object> list = new ArrayList<Object>();
		if (ReloadConfig.isUseCluster) {
			JedisCluster jedis = null;
			try {
				jedis = getJedisCluster();
				Set<byte[]> set = jedis.smembers(key.getBytes());
				if (set != null && !set.isEmpty()) {
					Iterator<byte[]> it = set.iterator();
					for (; it.hasNext();) {
						byte[] b = it.next();
						Object obj = new ObjectsTranscoder().deserialize(b);
						list.add(obj);
					}
				}
			} catch (Exception e) {
				logger.error(e.getMessage(), e);
			}
		} else {
			Jedis jedis = null;
			try {
				jedis = getJedis();
				Set<byte[]> set = jedis.smembers(key.getBytes());
				if (set != null && !set.isEmpty()) {
					Iterator<byte[]> it = set.iterator();
					for (; it.hasNext();) {
						byte[] b = it.next();
						Object obj = new ObjectsTranscoder().deserialize(b);
						list.add(obj);
					}
				}
			} catch (Exception e) {
				logger.error(e.getMessage(), e);
			}finally {
				jedis.close();
			}
		}
		return list;
	}

	public static void delAllObject(String key) {
		if (ReloadConfig.isUseCluster) {
			JedisCluster jedis = null;
			try {
				jedis = getJedisCluster();
				jedis.del(key.getBytes());
			} catch (Exception e) {
				logger.error(e.getMessage(), e);
			}
		} else {
			Jedis jedis = null;
			try {
				jedis = getJedis();
				jedis.del(key.getBytes());
			} catch (Exception e) {
				logger.error(e.getMessage(), e);
			}finally {
				jedis.close();
			}
		}
	}

	public static Long hset2(String key, String field, String value) {
		Long rtn = null;
		if (ReloadConfig.isUseCluster) {
			JedisCluster jedis = null;
			try {
				jedis = getJedisCluster();
				rtn = jedis.hset(key, field, value);
			} catch (Exception e) {
				logger.error(e.getMessage(), e);
			}
		} else {
			Jedis jedis = null;
			try {
				jedis = getJedis();
				rtn = jedis.hset(key, field, value);
			} catch (Exception e) {
				logger.error(e.getMessage(), e);
			}finally {
				jedis.close();
			}
		}
		return rtn;
	}

	public static void hdel2(String key) {
		if (ReloadConfig.isUseCluster) {
			JedisCluster jedis = null;
			try {
				jedis = getJedisCluster();
				jedis.del(key);
			} catch (Exception e) {
				logger.error(e.getMessage(), e);
			}
		} else {
			Jedis jedis = null;
			try {
				jedis = getJedis();
				jedis.del(key);
			} catch (Exception e) {
				logger.error(e.getMessage(), e);
			}finally {
				jedis.close();
			}
		}
	}

	public static void flush() {
		if (ReloadConfig.isUseCluster) {
			//没有flush操作；
		} else {
			Jedis jedis = null;
			jedis = getJedis();
			jedis.flushAll();
		}
	}

	/**
	 * 设置分布式锁
	 * 
	 * @param key
	 * @param value
	 * @return
	 */
	public static long setLock(String key, String value) {
		Long rtn = null;
		if (ReloadConfig.isUseCluster) {
			JedisCluster jedis = null;
			try {
				jedis = getJedisCluster();
				rtn = jedis.setnx(key, value);
				jedis.expire(key, EXPIRE);
			} catch (Exception e) {
				logger.error(e.getMessage(), e);
			}
		} else {
			Jedis jedis = null;
			try {
				jedis = getJedis();
				rtn = jedis.setnx(key, value);
				jedis.expire(key, EXPIRE);
			} catch (Exception e) {
				logger.error(e.getMessage(), e);
			}finally {
				jedis.close();
			}
		}
		return rtn;
	}

	/**
	 * 释放锁
	 * 
	 * @param key
	 * @return
	 */
	public static long delLock(String key) {
		Long rtn = null;
		if (ReloadConfig.isUseCluster) {
			JedisCluster jedis = null;
			try {
				jedis = getJedisCluster();
				rtn = jedis.del(key);
			} catch (Exception e) {
				logger.error(e.getMessage(), e);
			}
		} else {
			Jedis jedis = null;
			try {
				jedis = getJedis();
				rtn = jedis.del(key);
			} catch (Exception e) {
				logger.error(e.getMessage(), e);
			}finally {
				jedis.close();
			}
		}

		return rtn;
	}

	/**
	 * 存储子调用链的list
	 * 
	 * @param dateKey
	 * @param cidList
	 */
	public static void memoryCid(String dateKey, String cid) {
		if (ReloadConfig.isUseCluster) {
			JedisCluster jedis = null;
			try {
				jedis = getJedisCluster();
				jedis.sadd(dateKey, cid);
				jedis.expire(dateKey, EXPIRE);
			} catch (Exception e) {
				logger.error(e.getMessage(), e);
			}
		} else {
			Jedis jedis = null;
			try {
				jedis = getJedis();
				jedis.sadd(dateKey, cid);
				jedis.expire(dateKey, EXPIRE);
			} catch (Exception e) {
				logger.error(e.getMessage(), e);
			} finally {
				jedis.close();
			}
		}
	}

	/**
	 * 获取调用链list
	 * 
	 * @param dateKey
	 * @return
	 */
	public static Set<String> getAllCids(String dateKey) {
		Set<String> set = null;
		if (ReloadConfig.isUseCluster) {
			JedisCluster jedis = null;
			try {
				jedis = getJedisCluster();
				set = jedis.smembers(dateKey);
			} catch (Exception e) {
				logger.error(e.getMessage(), e);
			}
		} else {
			Jedis jedis = null;
			try {
				jedis = getJedis();
				set = jedis.smembers(dateKey);
			} catch (Exception e) {
				logger.error(e.getMessage(), e);
			} finally {
				jedis.close();
			}
		}
		return set;
	}
}
